// 定义图层类型枚举
enum LayerType {
  Point = "circle",
  Line = "line",
  Fill = "fill",
  Symbol = "symbol",
  Raster = "raster",
  geojson = "geojson",
  custom = "custom"
}

// 定义图层配置接口
interface LayerConfig {
  id: string;
  type: LayerType;
  source?: mapboxgl.AnySourceData;
  paint?: mapboxgl.LayerPaintPropertyMap;
  layout?: mapboxgl.LayerLayoutPropertyMap;
  filter?: any;
  beforeLayerId?: string; // 新增属性，用于指定添加图层时的前置图层 ID
  properties?: any;
  onAdd?: any;
  render?: any;
  renderingMode?: any;
}

// 定义图层管理器状态
interface LayerManagerState {
  map: mapboxgl.Map;
  layerOrder: string[];
}

// 初始化图层管理器，传入一个mapboxgl.Map对象作为参数
function initLayerManager(map: mapboxgl.Map): LayerManagerState {
  // 返回一个包含map和layerOrder的LayerManagerState对象
  return {
    map,
    layerOrder: []
  };
}

// 添加图层函数
function addLayer(state: LayerManagerState, config: LayerConfig): void {
  const { id, type, source, paint, layout, beforeLayerId, properties, filter, onAdd, render, renderingMode } = config;

  // 判断图层是否已经存在，如果存在则直接返回
  if (state.map.getLayer(id)) {
    console.log(`图层 ${id} 已存在，跳过添加操作。`);
    return;
  }

  // 如果state.map中没有id对应的source，则添加source
  if (!state.map.getSource(id) && source) {
    try {
      state.map.addSource(id, source);
    } catch (error) {
      console.error(`添加数据源 ${id} 时出错:`, error);
      return;
    }
  }

  let layerConfig = {
    id,
    type,
    source: id,
    paint: paint ? paint : {},
    layout: layout ? layout : {},
    properties: properties ? properties : {}
  };

  if (filter) {
    layerConfig.filter = filter;
  }
  if (onAdd) {
    layerConfig.onAdd = onAdd;
  }
  if (render) {
    layerConfig.render = render;
  }
  if (renderingMode) {
    layerConfig.renderingMode = renderingMode;
  }

  // 如果有beforeLayerId，则在beforeLayerId之前添加图层
  try {
    if (beforeLayerId) {
      state.map.addLayer(layerConfig, beforeLayerId);
    } else {
      state.map.addLayer(layerConfig);
    }
  } catch (error) {
    console.error(`添加图层 ${id} 时出错:`, error);
    return;
  }

  // 将id添加到layerOrder中
  if (!state.layerOrder.includes(id)) {
    state.layerOrder.push(id);
  }
}

// 函数removeLayer用于从LayerManagerState中移除指定id的图层
// 移除指定id的图层和源，并从state.layerOrder中移除该图层
function removeLayer(state: LayerManagerState, layerId: string): void {
  // 如果state.map中存在指定id的图层，则移除该图层
  if (state.map.getLayer(layerId)) {
    state.map.removeLayer(layerId);
  }
  // 如果state.map中存在指定id的源，则移除该源
  if (state.map.getSource(layerId)) {
    state.map.removeSource(layerId);
  }
  // 获取指定id在state.layerOrder中的索引
  const index = state.layerOrder.indexOf(layerId);
  // 如果索引大于-1，则说明该图层存在于state.layerOrder中，将其从state.layerOrder中移除
  if (index > -1) {
    state.layerOrder.splice(index, 1);
  }
}

// 移除所有图层和数据源的函数
function removeAllLayers(state: LayerManagerState): void {
  const usedSources = new Set<string>();

  // 先移除所有图层
  state.map.getStyle().layers.forEach((layer: { id: string; source: string }) => {
    if (state.map.getLayer(layer.id)) {
      state.map.removeLayer(layer.id);
      usedSources.add(layer.source);
    }
  });

  // 再移除所有使用过的数据源
  usedSources.forEach(sourceId => {
    if (state.map.getSource(sourceId)) {
      state.map.removeSource(sourceId);
    }
  });

  // 清空 state.layerOrder
  state.layerOrder = [];
}

// 根据传入的state和layerId，显示指定图层
function showLayer(state: LayerManagerState, layerId: string): void {
  // 如果state中的map存在指定layerId的图层
  if (state.map.getLayer(layerId)) {
    // 将指定图层的可见性设置为可见
    state.map.setLayoutProperty(layerId, "visibility", "visible");
  }
}

// 隐藏图层函数
// 参数：state：LayerManagerState，layerId：string
// 返回值：void
function hideLayer(state: LayerManagerState, layerId: string): void {
  // 如果state.map中存在layerId对应的图层
  if (state.map.getLayer(layerId)) {
    // 将该图层的可见性设置为'none'
    state.map.setLayoutProperty(layerId, "visibility", "none");
  }
}

// 函数：判断state中是否存在layerId对应的图层
// 参数：state：LayerManagerState类型，layerId：string类型
// 返回值：boolean类型，表示是否存在layerId对应的图层
function hasLayer(state: LayerManagerState, layerId: string): boolean {
  // 获取state中layerId对应的图层
  return state.map.getLayer(layerId) !== undefined;
}

// 根据传入的state和layerId获取对应的mapboxgl.Layer对象
function getLayerInfo(state: LayerManagerState, layerId: string): mapboxgl.Layer | undefined {
  // 从state的map对象中获取对应的layerId的Layer对象
  return state.map.getLayer(layerId);
}

// 更新图层样式
// state: 图层管理状态
// layerId: 图层ID
// paint: 图层样式属性
// layout: 图层布局属性
function updateLayerStyle(
  state: LayerManagerState,
  layerId: string,
  paint?: mapboxgl.LayerPaintPropertyMap,
  layout?: mapboxgl.LayerLayoutPropertyMap
): void {
  // 如果地图中存在该图层
  if (state.map.getLayer(layerId)) {
    // 如果存在图层样式属性
    if (paint) {
      // 遍历图层样式属性
      for (const [key, value] of Object.entries(paint)) {
        // 设置图层样式属性
        state.map.setPaintProperty(layerId, key, value);
      }
    }
    // 如果存在图层布局属性
    if (layout) {
      // 遍历图层布局属性
      for (const [key, value] of Object.entries(layout)) {
        // 设置图层布局属性
        state.map.setLayoutProperty(layerId, key, value);
      }
    }
  }
}

// 更新数据源
function updateSource(state: LayerManagerState, sourceId: string, source: any): void {
  // 如果地图中存在该数据源
  if (state.map.getSource(sourceId)) {
    // 更新数据源
    state.map.getSource(sourceId).setData(source);
  }
}

// 根据传入的图层ID，切换图层的可见性
function toggleLayerVisibility(state: LayerManagerState, layerId: string): void {
  // 判断图层是否存在
  if (state.map.getLayer(layerId)) {
    // 获取图层的可见性属性
    const visibility = state.map.getLayoutProperty(layerId, "visibility") as string;
    // 如果图层可见，则隐藏图层
    if (visibility === "visible") {
      hideLayer(state, layerId);
      // 如果图层不可见，则显示图层
    } else {
      showLayer(state, layerId);
    }
  }
}

// 将图层移动到最上层
function moveLayerToTop(state: LayerManagerState, layerId: string): void {
  // 如果图层存在
  if (state.map.getLayer(layerId)) {
    // 将图层移动到最上层
    state.map.moveLayer(layerId);
    // 获取图层的索引
    const index = state.layerOrder.indexOf(layerId);
    // 如果图层存在
    if (index > -1) {
      // 从图层顺序中移除图层
      state.layerOrder.splice(index, 1);
      // 将图层添加到图层顺序的末尾
      state.layerOrder.push(layerId);
    }
  }
}

// 将图层移动到底部
function moveLayerToBottom(state: LayerManagerState, layerId: string): void {
  // 如果图层存在
  if (state.map.getLayer(layerId)) {
    // 获取图层顺序中的第一个图层ID
    const firstLayerId = state.layerOrder[0];
    // 如果第一个图层ID存在
    if (firstLayerId) {
      // 将当前图层移动到第一个图层之前
      state.map.moveLayer(layerId, firstLayerId);
    }
    // 获取当前图层在图层顺序中的索引
    const index = state.layerOrder.indexOf(layerId);
    // 如果索引大于-1，说明图层存在
    if (index > -1) {
      // 从图层顺序中删除当前图层
      state.layerOrder.splice(index, 1);
      // 将当前图层添加到图层顺序的第一个位置
      state.layerOrder.unshift(layerId);
    }
  }
}

// 将指定图层移动到另一个图层之上 
function moveLayerAbove(
  // 图层管理器状态
  state: LayerManagerState,
  // 要移动的图层的ID
  layerId: string,
  // 要移动到的图层的ID
  aboveLayerId: string
): void {
  // 如果要移动的图层和要移动到的图层都存在
  if (state.map.getLayer(layerId) && state.map.getLayer(aboveLayerId)) {
    // 将要移动的图层移动到要移动到的图层之上
    state.map.moveLayer(layerId, aboveLayerId);
    // 获取要移动的图层的索引
    const index = state.layerOrder.indexOf(layerId);
    // 获取要移动到的图层的索引
    const aboveIndex = state.layerOrder.indexOf(aboveLayerId);
    // 如果要移动的图层和要移动到的图层都存在
    if (index > -1 && aboveIndex > -1) {
      // 从图层顺序中删除要移动的图层
      state.layerOrder.splice(index, 1);
      // 在要移动到的图层的索引之后插入要移动的图层
      state.layerOrder.splice(aboveIndex + 1, 0, layerId);
    }
  }
}

// 将指定图层移动到指定图层的下方
function moveLayerBelow(
  // 图层管理器状态
  state: LayerManagerState,
  // 要移动的图层的ID
  layerId: string,
  // 要移动到的图层的ID
  belowLayerId: string
): void {
  // 如果要移动的图层和要移动到的图层都存在
  if (state.map.getLayer(layerId) && state.map.getLayer(belowLayerId)) {
    // 获取要移动到的图层的索引
    const belowIndex = state.layerOrder.indexOf(belowLayerId);
    // 获取要移动到的图层之前的图层的ID
    const beforeLayerId = belowIndex > 0 ? state.layerOrder[belowIndex - 1] : undefined;
    // 将要移动的图层移动到指定位置
    state.map.moveLayer(layerId, beforeLayerId);
    // 获取要移动的图层的索引
    const index = state.layerOrder.indexOf(layerId);
    // 如果要移动的图层和要移动到的图层都存在
    if (index > -1 && belowIndex > -1) {
      // 从图层顺序中删除要移动的图层
      state.layerOrder.splice(index, 1);
      // 在要移动到的图层之后插入要移动的图层
      state.layerOrder.splice(belowIndex, 0, layerId);
    }
  }
}

// 根据LayerManagerState获取所有图层的id
function getAllLayerIds(state: LayerManagerState): string[] {
  // 返回state中的layerOrder数组
  return state.layerOrder;
}

export {
  LayerType,
  initLayerManager,
  addLayer,
  removeLayer,
  showLayer,
  hideLayer,
  hasLayer,
  getLayerInfo,
  updateLayerStyle,
  toggleLayerVisibility,
  moveLayerToTop,
  moveLayerToBottom,
  moveLayerAbove,
  moveLayerBelow,
  getAllLayerIds,
  removeAllLayers,
  updateSource
};
export type { LayerConfig };
